package utils;

import java.awt.Color;
import java.awt.Font;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;


import javax.imageio.ImageIO;


import jj.play.ns.nl.captcha.backgrounds.BackgroundProducer;
import jj.play.ns.nl.captcha.backgrounds.FlatColorBackgroundProducer;
import jj.play.ns.nl.captcha.backgrounds.GradiatedBackgroundProducer;
import jj.play.ns.nl.captcha.backgrounds.SquigglesBackgroundProducer;
import jj.play.ns.nl.captcha.backgrounds.TransparentBackgroundProducer;
import jj.play.ns.nl.captcha.gimpy.GimpyRenderer;
import jj.play.ns.nl.captcha.gimpy.RippleGimpyRenderer;
import jj.play.ns.nl.captcha.noise.CurvedLineNoiseProducer;
import jj.play.ns.nl.captcha.text.renderer.DefaultWordRenderer;

import play.exceptions.UnexpectedException;

import play.mvc.Http.Response;
/**
 * @author yangzhi
 * @date 2019/1/3
 */
public class ImageUtils {
	/**
	 * Create a captche image
	 */
	public static CaptchaNew captcha(int width, int height) {
		return new CaptchaNew(width, height);
	}

	/**
	 * Create a 150x150 captcha image
	 */
	public static CaptchaNew captcha() {
		return captcha(150, 50);
	}

	/**
	 * A captcha image.
	 */
	public static class CaptchaNew extends InputStream {

		public String text = null;
		public BackgroundProducer background = new TransparentBackgroundProducer();
		public GimpyRenderer gimpy = new RippleGimpyRenderer();
		public Color textColor = Color.BLACK;
		public List<Font> fonts = new ArrayList<Font>(2);
		public int w, h;
		public Color noise = null;

		public CaptchaNew(int w, int h) {
			this.w = w;
			this.h = h;
			this.fonts.add(new Font("Arial", Font.BOLD, 40));
			this.fonts.add(new Font("Courier", Font.BOLD, 40));
		}

		/**
		 * Tell the captche to draw a text and retrieve it
		 */
		public String getText() {
			if (Utils.isNullOrEmpty(text)) {
				return getText(4);
			}else{
				return  text;
			}
		}

		/**
		 * Tell the captche to draw a text using the specified color (ex.
		 * #000000) and retrieve it
		 */
		public String getText(String color) {
			this.textColor = Color.decode(color);
			return getText();
		}

		/**
		 * Tell the captche to draw a text of the specified size and retrieve it
		 */
		public String getText(int length) {
			String result= getText(length, "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789");
			text = result;
			return  text;
		}

		/**
		 * Tell the captche to draw a text of the specified size using the
		 * specified color (ex. #000000) and retrieve it
		 */
		public String getText(String color, int length) {
			this.textColor = Color.decode(color);
			return getText(length);
		}

		public String getText(int length, String chars) {
			char[] charsArray = chars.toCharArray();
			Random random = new Random(System.currentTimeMillis());
			StringBuffer sb = new StringBuffer(length);
			for (int i = 0; i < length; i++) {
				sb.append(charsArray[random.nextInt(charsArray.length)]);
			}
			text = sb.toString();
			return text;
		}

		public String getText(String color, int length, String chars) {
			this.textColor = Color.decode(color);
			return getText(length, chars);
		}

		/**
		 * Add noise to the captcha.
		 */
		public CaptchaNew addNoise() {
			noise = Color.BLACK;
			return this;
		}

		/**
		 * Add noise to the captcha.
		 */
		public CaptchaNew addNoise(String color) {
			noise = Color.decode(color);
			return this;
		}

		/**
		 * Set a gradient background.
		 */
		public CaptchaNew setBackground(String from, String to) {
			GradiatedBackgroundProducer bg = new GradiatedBackgroundProducer();
			bg.setFromColor(Color.decode(from));
			bg.setToColor(Color.decode(to));
			background = bg;
			return this;
		}

		/**
		 * Set a solid background.
		 */
		public CaptchaNew setBackground(String color) {
			background = new FlatColorBackgroundProducer(Color.decode(color));
			return this;
		}

		/**
		 * Set a squiggles background
		 */
		public CaptchaNew setSquigglesBackground() {
			background = new SquigglesBackgroundProducer();
			return this;
		} // ~~ rendering

		ByteArrayInputStream bais = null;

		@Override
		public int read() throws IOException {
			check();
			return bais.read();
		}

		@Override
		public int read(byte[] b) throws IOException {
			check();
			return bais.read(b);
		}

		void check() {
			try {
				if (bais == null) {
					/*if (text == null) {
						text = getText();
					}*/
					BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
					DefaultWordRenderer renderer = new DefaultWordRenderer(textColor, fonts);
					bi = background.addBackground(bi);
					renderer.render(text, bi);
					if (noise != null) {
						new CurvedLineNoiseProducer(noise, 3.0f).makeNoise(bi);
					}
					//gimpy.gimp(bi);
					ByteArrayOutputStream baos = new ByteArrayOutputStream();
					ImageIO.write(bi, "png", baos);
					bais = new ByteArrayInputStream(baos.toByteArray());
					//
					Response.current().contentType = "image/png";
				}
			} catch (Exception e) {
				throw new UnexpectedException(e);
			}
		}
	}
}
